package com.woniuxy.gateway.filter;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.woniuxy.commons.enums.TokenEnum;
import com.woniuxy.commons.util.JwtUtil;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;

//@Component
public class MyGlobalFilter implements GlobalFilter, Ordered {
    @Resource
    private RedisTemplate<String,Object> redisTemplate;
    //执行过滤方法和zuul中的run方法一样
    //ServerWebExchange：网络服务交换机
    //GatewayFilterChain：过滤器链
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //1获取request
        ServerHttpRequest request = exchange.getRequest();
        //2获取请求头（token）
        List<String> tokens = request.getHeaders().get("authorization");
        String token=null;
        if(tokens != null && tokens.size()!=0){
            token = tokens.get(0);
        }
        List<String> refreshtokens = request.getHeaders().get("refreshtoken");
        String refreshtoken=null;
        if(refreshtokens != null && refreshtokens.size()!=0){
            refreshtoken = refreshtokens.get(0);
        }
        //3获取uri
        String uri = request.getURI().getPath();
        System.out.println("url:"+uri);

        //4判断是否需要认证  登录
        if(!requireAuth(uri)){
            System.out.println("登录过，不需要认证");
            return chain.filter(exchange);
        }
        //5需要认证:判断refreshtoken和token存在
        if(refreshtoken==null || token == null){
            //没登录
            System.out.println("未登录");
            DataBuffer buffer = result(exchange);
            //中断
            return exchange.getResponse().writeWith(Mono.just(buffer));
        }
        //6此处说明两个都有，在判断合法：判断refreshtoken合法，从redis查找refreshtoken
        /*if(redisTemplate.hasKey(refreshtoken)){
            System.out.println("refreshtoken合法");
        }else{
            System.out.println("refreshtoken不合法");
            DataBuffer buffer = result(exchange);
            //中断
            return exchange.getResponse().writeWith(Mono.just(buffer));
        }*/

        //7判断token合法
        if(JwtUtil.verify(token) == TokenEnum.TOKEN_BAD){
            //伪造，不放行
            System.out.println("伪造，不放行");
            //没登录
            DataBuffer buffer = result(exchange);
            //中断
            return exchange.getResponse().writeWith(Mono.just(buffer));
        }else if(JwtUtil.verify(token) == TokenEnum.TOKEN_EXPIRE){
            //过期，生成新的返回放行
            System.out.println("token过期");
            //获取账号
            String account = JwtUtil.getUname(token);
            String token1 = JwtUtil.generateToken(account);
            //返回数据
            exchange.getResponse().getHeaders().add("authorization",token1);
            //暴露头
            exchange.getResponse().getHeaders().add("Access-Control-Expose-Headers","authorization,refreshtoken");
            //修改redis中的refreshtoken
            
        }

        //8执行到此处证明合法的，放行
        System.out.println("token合法放行");

        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return 0;
    }
    //判断是否需要登录
    private boolean requireAuth(String uri){
        //存放不需要登录的URI
        List<String> uris = Arrays.asList(
                "/auth/login","/auth/regist/","/file/upload"
        );
        for(String uri1 : uris){
            if(uri.startsWith(uri1)){
                //不需要认证
                return false;
            }
        }
        return true;
    }
    //返回结果
    private DataBuffer result(ServerWebExchange exchange){
        //假设没有权限，请求终止
        ServerHttpResponse response = exchange.getResponse();
        try{
            //1、转成json数据格式
            String data = new ObjectMapper().writeValueAsString("登录权限不够，请登录！");
            //转byte[]
            byte[] bytes = data.getBytes(StandardCharsets.UTF_8);
            //将bytes放如缓冲区
            DataBuffer buffer = response.bufferFactory().wrap(bytes);
            //设置响应头
            response.getHeaders().add("Content-Type","application/json;charset=utf-8");
            //写出数据
            return buffer;
        }catch (Exception e){
            System.out.println("过滤器写出数据报错");
        }
        return null;
    }
}
